<!DOCTYPE html>





<html lang="zh-CN">
<head>
  <!-- hexo-inject:begin --><!-- hexo-inject:end --><meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 4.2.1">
  <link rel="apple-touch-icon" sizes="180x180" href="/sunpages/images/apple-touch-icon-next.png?v=7.4.0">
  <link rel="icon" type="image/png" sizes="32x32" href="/sunpages/images/favicon-32x32-next.png?v=7.4.0">
  <link rel="icon" type="image/png" sizes="16x16" href="/sunpages/images/favicon-16x16-next.png?v=7.4.0">
  <link rel="mask-icon" href="/sunpages/images/logo.svg?v=7.4.0" color="#222">

<link rel="stylesheet" href="/sunpages/css/main.css?v=7.4.0">


<link rel="stylesheet" href="/sunpages/lib/font-awesome/css/font-awesome.min.css?v=4.7.0">


<script id="hexo-configurations">
  var NexT = window.NexT || {};
  var CONFIG = {
    root: '/sunpages/',
    scheme: 'Pisces',
    version: '7.4.0',
    exturl: false,
    sidebar: {"position":"left","display":"post","offset":12,"onmobile":false},
    copycode: {"enable":true,"show_result":false,"style":null},
    back2top: {"enable":true,"sidebar":false,"scrollpercent":true},
    bookmark: {"enable":false,"color":"#222","save":"auto"},
    fancybox: false,
    mediumzoom: false,
    lazyload: false,
    pangu: false,
    algolia: {
      appID: '',
      apiKey: '',
      indexName: '',
      hits: {"per_page":10},
      labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
    },
    localsearch: {"enable":true,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false},
    path: 'search.xml',
    motion: {"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},
    translation: {
      copy_button: '复制',
      copy_success: '复制成功',
      copy_failure: '复制失败'
    },
    sidebarPadding: 40
  };
</script>

  <meta name="description" content="2 Switching Hub[TOC]2.1 Switching Hub">
<meta property="og:type" content="article">
<meta property="og:title" content="ryu控制器实现集线器">
<meta property="og:url" content="https://yuandaima1.gitee.io/sunpages/2019/04/06/2/index.html">
<meta property="og:site_name" content="SunPages">
<meta property="og:description" content="2 Switching Hub[TOC]2.1 Switching Hub">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="http://ipic-picgo.oss-cn-beijing.aliyuncs.com/2019-05-10-133501.jpg">
<meta property="og:image" content="http://ipic-picgo.oss-cn-beijing.aliyuncs.com/2019-05-10-133821.jpg">
<meta property="og:image" content="http://ipic-picgo.oss-cn-beijing.aliyuncs.com/2019-05-10-134423.jpg">
<meta property="og:image" content="http://ipic-picgo.oss-cn-beijing.aliyuncs.com/2019-05-10-134853.jpg">
<meta property="og:image" content="http://ipic-picgo.oss-cn-beijing.aliyuncs.com/2019-05-11-053905.jpg">
<meta property="og:image" content="http://ipic-picgo.oss-cn-beijing.aliyuncs.com/2019-05-11-054538.jpg">
<meta property="og:image" content="http://ipic-picgo.oss-cn-beijing.aliyuncs.com/2019-05-11-061623.jpg">
<meta property="og:image" content="http://ipic-picgo.oss-cn-beijing.aliyuncs.com/2019-05-11-064100.jpg">
<meta property="og:image" content="http://ipic-picgo.oss-cn-beijing.aliyuncs.com/2019-05-11-064628.jpg">
<meta property="og:image" content="http://ipic-picgo.oss-cn-beijing.aliyuncs.com/2019-05-11-070404.jpg">
<meta property="article:published_time" content="2019-04-06T12:10:33.000Z">
<meta property="article:modified_time" content="2019-09-12T09:35:05.000Z">
<meta property="article:author" content="sunhanwu">
<meta property="article:tag" content="SDN">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="http://ipic-picgo.oss-cn-beijing.aliyuncs.com/2019-05-10-133501.jpg">
  <link rel="canonical" href="https://yuandaima1.gitee.io/sunpages/2019/04/06/2/">


<script id="page-configurations">
  // https://hexo.io/docs/variables.html
  CONFIG.page = {
    sidebar: "",
    isHome: false,
    isPost: true,
    isPage: false,
    isArchive: false
  };
</script>

  <title>ryu控制器实现集线器 | SunPages</title>
  








  <noscript>
  <style>
  .use-motion .brand,
  .use-motion .menu-item,
  .sidebar-inner,
  .use-motion .post-block,
  .use-motion .pagination,
  .use-motion .comments,
  .use-motion .post-header,
  .use-motion .post-body,
  .use-motion .collection-header { opacity: initial; }

  .use-motion .logo,
  .use-motion .site-title,
  .use-motion .site-subtitle {
    opacity: initial;
    top: initial;
  }

  .use-motion .logo-line-before i { left: initial; }
  .use-motion .logo-line-after i { right: initial; }
  </style>
</noscript><!-- hexo-inject:begin --><!-- hexo-inject:end -->

</head>

<body itemscope itemtype="http://schema.org/WebPage" lang="zh-CN">
  <!-- hexo-inject:begin --><!-- hexo-inject:end --><div class="container use-motion">
    <div class="headband"></div>

    <header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-meta">

    <div>
      <a href="/sunpages/" class="brand" rel="start">
        <span class="logo-line-before"><i></i></span>
        <span class="site-title">SunPages</span>
        <span class="logo-line-after"><i></i></span>
      </a>
    </div>
        <h1 class="site-subtitle" itemprop="description">屁话少说,放码过来！</h1>
      
  </div>

  <div class="site-nav-toggle">
    <button aria-label="切换导航栏">
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
    </button>
  </div>
</div>


<nav class="site-nav">
  
  <ul id="menu" class="menu">
      
      
      
        
        <li class="menu-item menu-item-home">
      
    

    <a href="/sunpages/" rel="section"><i class="menu-item-icon fa fa-fw fa-home"></i> <br>首页</a>

  </li>
      
      
      
        
        <li class="menu-item menu-item-about">
      
    

    <a href="/sunpages/about/" rel="section"><i class="menu-item-icon fa fa-fw fa-user"></i> <br>关于</a>

  </li>
      
      
      
        
        <li class="menu-item menu-item-tags">
      
    

    <a href="/sunpages/tags/" rel="section"><i class="menu-item-icon fa fa-fw fa-tags"></i> <br>标签</a>

  </li>
      
      
      
        
        <li class="menu-item menu-item-categories">
      
    

    <a href="/sunpages/categories/" rel="section"><i class="menu-item-icon fa fa-fw fa-th"></i> <br>分类</a>

  </li>
      
      
      
        
        <li class="menu-item menu-item-archives">
      
    

    <a href="/sunpages/archives/" rel="section"><i class="menu-item-icon fa fa-fw fa-archive"></i> <br>归档</a>

  </li>
      
      
      
        
        <li class="menu-item menu-item-photos">
      
    

    <a href="/sunpages/photo/" rel="section"><i class="menu-item-icon fa fa-fw fa-image"></i> <br>Photos</a>

  </li>
      <li class="menu-item menu-item-search">
        <a href="javascript:;" class="popup-trigger">
        
          <i class="menu-item-icon fa fa-search fa-fw"></i> <br>搜索</a>
      </li>
    
  </ul>

</nav>
  <div class="site-search">
    <div class="popup search-popup">
    <div class="search-header">
  <span class="search-icon">
    <i class="fa fa-search"></i>
  </span>
  <div class="search-input" id="search-input"></div>
  <span class="popup-btn-close">
    <i class="fa fa-times-circle"></i>
  </span>
</div>
<div class="algolia-results">
  <div id="algolia-stats"></div>
  <div id="algolia-hits"></div>
  <div id="algolia-pagination" class="algolia-pagination"></div>
</div>

  
</div>
<div class="search-pop-overlay"></div>

  </div>
</div>
    </header>

    
  <div class="back-to-top">
    <i class="fa fa-arrow-up"></i>
    <span>0%</span>
  </div>

  <a href="https://github.com/sunhanwu" class="github-corner" title="Follow me on GitHub" aria-label="Follow me on GitHub" rel="noopener" target="_blank"><svg width="80" height="80" viewBox="0 0 250 250" aria-hidden="true"><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path></svg></a>


    <main id="main" class="main">
      <div class="main-inner">
        <div class="content-wrap">
            

          <div id="content" class="content">
            

  <div id="posts" class="posts-expand">
      <article itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block post">
    <link itemprop="mainEntityOfPage" href="https://yuandaima1.gitee.io/sunpages/sunpages/2019/04/06/2/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="sunhanwu">
      <meta itemprop="description" content="Talk is cheap, show me the code!">
      <meta itemprop="image" content="http://ipic-picgo.oss-cn-beijing.aliyuncs.com/2019-09-12-logo.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="SunPages">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">ryu控制器实现集线器

          
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              
                
              

              <time title="创建时间：2019-04-06 20:10:33" itemprop="dateCreated datePublished" datetime="2019-04-06T20:10:33+08:00">2019-04-06</time>
            </span>
          
            

            
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="fa fa-calendar-check-o"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2019-09-12 17:35:05" itemprop="dateModified" datetime="2019-09-12T17:35:05+08:00">2019-09-12</time>
              </span>
            
          
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/sunpages/categories/RYU%E6%8E%A7%E5%88%B6%E5%99%A8/" itemprop="url" rel="index"><span itemprop="name">RYU控制器</span></a></span>

                
                
              
            </span>
          

          
  
  <span class="post-meta-item">
    
      <span class="post-meta-item-icon">
        <i class="fa fa-comment-o"></i>
      </span>
        
      
      <span class="post-meta-item-text">Valine：</span>
    
    <a title="valine" href="/sunpages/2019/04/06/2/#comments" itemprop="discussionUrl"><span class="post-comments-count valine-comment-count" data-xid="/sunpages/2019/04/06/2/" itemprop="commentCount"></span></a>
  </span>
  
  
          <br>
            <span class="post-meta-item" title="本文字数">
              <span class="post-meta-item-icon">
                <i class="fa fa-file-word-o"></i>
              </span>
              
                <span class="post-meta-item-text">本文字数：</span>
              
              <span>12k</span>
            </span>
          
            <span class="post-meta-item" title="阅读时长">
              <span class="post-meta-item-icon">
                <i class="fa fa-clock-o"></i>
              </span>
              
                <span class="post-meta-item-text">阅读时长 &asymp;</span>
              
              <span>11 分钟</span>
            </span>
          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
        <h1 id="2-Switching-Hub"><a href="#2-Switching-Hub" class="headerlink" title="2 Switching Hub"></a>2 Switching Hub</h1><p>[TOC]</p><h2 id="2-1-Switching-Hub"><a href="#2-1-Switching-Hub" class="headerlink" title="2.1 Switching Hub"></a>2.1 Switching Hub</h2><a id="more"></a>
<p>交换集线器有很多种不同的功能，在这我们看看拥有以下功能的集线器：</p>
<ul>
<li>能够学习集线器端口连接主机的MAC地址并将其保存在MAC地址表中</li>
<li>当收到MAC地址已知的报文时，将其转发到对应端口</li>
<li>当收到地址未知的报文的时候，进行泛洪</li>
</ul>
<p>让我们用ryu来实现这种功能的交换机</p>
<h2 id="2-2-openflow交换集线器"><a href="#2-2-openflow交换集线器" class="headerlink" title="2.2 openflow交换集线器"></a>2.2 openflow交换集线器</h2><p>openflow交换机可以实现下列功能通过接受控制器的指令(例如ryu控制器)</p>
<ul>
<li>改写接受数据包的地址或者从特定端口转发数据包</li>
<li>转发数据包到控制器(packet-In)</li>
<li>控制器从指定端口转发数据包(Packet-Out)</li>
</ul>
<p>可以实现组合了这些功能的交换集线器。<br>首先，您需要使用Packet-In功能来学习MAC地址。控制器可以使用Packet-In函数从交换机接收数据包。交换机分析收到的数据包，以了解主机的MAC地址和有关连接端口的信息。<br>学习之后，交换机传输接收的数据包。交换机调查数据包的目的MAC地址是否属于已知主机。根据调查结果，交换机执行以下处理。</p>
<ul>
<li>如果主机已经是已知主机…使用Packet-Out功能从连接的端口转发数据包。</li>
<li>如果主机是未知主机…使用Packet-Out功能执行泛洪</li>
</ul>
<p>以下使用附图以逐步的方式说明上述操作：</p>
<ol>
<li><p>初始状态</p>
<p>初始状态下流表为空，假设主机A连接端口1，主机B连接端口4，主机C连接端口3</p>
<div align="center"><img src="http://ipic-picgo.oss-cn-beijing.aliyuncs.com/2019-05-10-133501.jpg" width="600"></div>
</li>
<li><p>主机A-&gt; 主机B</p>
<p>当数据包从主机A发送到主机B的时候，一个Packet-In消息将会被发送到控制器并且主机A的MAC地址将会被端口1学习。但是由于主机B的端口还不知道，因此数据包被泛洪到除了端口1以外的所有端口并且被主机B和主机C接受。</p>
<div align="center"><img src="http://ipic-picgo.oss-cn-beijing.aliyuncs.com/2019-05-10-133821.jpg" width="600"></div>

<ul>
<li><p>Packet-In：</p>
<p>入端口:1</p>
<p>目的主机：B</p>
<p>源主机：A</p>
</li>
<li><p>Packet-Out：</p>
<p>动作：输出：泛洪</p>
</li>
</ul>
</li>
<li><p>主机B-&gt;主机A</p>
<p>当主机B回应主机A的数据包返回的时候，由于已经有一个流表项被加入到流表中所以数据包将被转发到端口1，所以主机C将不会收到B发送的数据包</p>
<div align="center"><img src="http://ipic-picgo.oss-cn-beijing.aliyuncs.com/2019-05-10-134423.jpg" width="600"></div>

<ul>
<li><p>Packet-In:</p>
<p>入端口：4</p>
<p>目的主机：主机A</p>
<p>源主机：主机B</p>
</li>
<li><p>Packet-Out:</p>
<p>动作：输出：端口1</p>
</li>
</ul>
</li>
<li><p>主机A-&gt;主机B</p>
<p>当主机A再一次向主机B发送数据包的时候，由于前面主机B回应数据包的时候，端口4已经学习到主机B的MAC地址，所以这一次数据包将会直接向端口4发送</p>
<div align="center"><img src="http://ipic-picgo.oss-cn-beijing.aliyuncs.com/2019-05-10-134853.jpg" width="600"></div>

<ul>
<li><p>Packet-In</p>
<p>入端口：1</p>
<p>目的主机：主机B</p>
<p>源主机：主机A</p>
</li>
<li><p>Packet-Out：</p>
<p>动作：输出：端口4</p>
</li>
</ul>
</li>
</ol>
<p>下面我们来看看交换集线器的ryu源码实现</p>
<h2 id="2-3-使用Ryu实现交换集线器"><a href="#2-3-使用Ryu实现交换集线器" class="headerlink" title="2.3 使用Ryu实现交换集线器"></a>2.3 使用Ryu实现交换集线器</h2><p>源码在ryu/app/example_switch_13.py</p>
<p>除了上述之外，还有simple_switch.py（OpenFlow 1.0）和simple_switch_12.py（OpenFlow 1.2），具体取决于OpenFlow的版本，但我们看一下支持OpenFlow 1.3的实现</p>
<p>源代码很短，因此我们在下面显示了完整的源代码</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Copyright (C) 2016 Nippon Telegraph and Telephone Corporation.</span></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment"># Licensed under the Apache License, Version 2.0 (the "License");</span></span><br><span class="line"><span class="comment"># you may not use this file except in compliance with the License.</span></span><br><span class="line"><span class="comment"># You may obtain a copy of the License at</span></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment">#    http://www.apache.org/licenses/LICENSE-2.0</span></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment"># Unless required by applicable law or agreed to in writing, software</span></span><br><span class="line"><span class="comment"># distributed under the License is distributed on an "AS IS" BASIS,</span></span><br><span class="line"><span class="comment"># WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or</span></span><br><span class="line"><span class="comment"># implied.</span></span><br><span class="line"><span class="comment"># See the License for the specific language governing permissions and</span></span><br><span class="line"><span class="comment"># limitations under the License.</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">from</span> ryu.base <span class="keyword">import</span> app_manager</span><br><span class="line"><span class="keyword">from</span> ryu.controller <span class="keyword">import</span> ofp_event</span><br><span class="line"><span class="keyword">from</span> ryu.controller.handler <span class="keyword">import</span> CONFIG_DISPATCHER, MAIN_DISPATCHER</span><br><span class="line"><span class="keyword">from</span> ryu.controller.handler <span class="keyword">import</span> set_ev_cls</span><br><span class="line"><span class="keyword">from</span> ryu.ofproto <span class="keyword">import</span> ofproto_v1_3</span><br><span class="line"><span class="keyword">from</span> ryu.lib.packet <span class="keyword">import</span> packet</span><br><span class="line"><span class="keyword">from</span> ryu.lib.packet <span class="keyword">import</span> ethernet</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">ExampleSwitch13</span><span class="params">(app_manager.RyuApp)</span>:</span></span><br><span class="line">    OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION]</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self, *args, **kwargs)</span>:</span></span><br><span class="line">        super(ExampleSwitch13, self).__init__(*args, **kwargs)</span><br><span class="line">        <span class="comment"># initialize mac address table.</span></span><br><span class="line">        self.mac_to_port = &#123;&#125;</span><br><span class="line"></span><br><span class="line"><span class="meta">    @set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER)</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">switch_features_handler</span><span class="params">(self, ev)</span>:</span></span><br><span class="line">        datapath = ev.msg.datapath</span><br><span class="line">        ofproto = datapath.ofproto</span><br><span class="line">        parser = datapath.ofproto_parser</span><br><span class="line"></span><br><span class="line">        <span class="comment"># install the table-miss flow entry.</span></span><br><span class="line">        match = parser.OFPMatch()</span><br><span class="line">        actions = [parser.OFPActionOutput(ofproto.OFPP_CONTROLLER,</span><br><span class="line">                                          ofproto.OFPCML_NO_BUFFER)]</span><br><span class="line">        self.add_flow(datapath, <span class="number">0</span>, match, actions)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">add_flow</span><span class="params">(self, datapath, priority, match, actions)</span>:</span></span><br><span class="line">        ofproto = datapath.ofproto</span><br><span class="line">        parser = datapath.ofproto_parser</span><br><span class="line"></span><br><span class="line">        <span class="comment"># construct flow_mod message and send it.</span></span><br><span class="line">        inst = [parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS,</span><br><span class="line">                                             actions)]</span><br><span class="line">        mod = parser.OFPFlowMod(datapath=datapath, priority=priority,</span><br><span class="line">                                match=match, instructions=inst)</span><br><span class="line">        datapath.send_msg(mod)</span><br><span class="line"></span><br><span class="line"><span class="meta">    @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">_packet_in_handler</span><span class="params">(self, ev)</span>:</span></span><br><span class="line">        msg = ev.msg</span><br><span class="line">        datapath = msg.datapath</span><br><span class="line">        ofproto = datapath.ofproto</span><br><span class="line">        parser = datapath.ofproto_parser</span><br><span class="line"></span><br><span class="line">        <span class="comment"># get Datapath ID to identify OpenFlow switches.</span></span><br><span class="line">        dpid = datapath.id</span><br><span class="line">        self.mac_to_port.setdefault(dpid, &#123;&#125;)</span><br><span class="line"></span><br><span class="line">        <span class="comment"># analyse the received packets using the packet library.</span></span><br><span class="line">        pkt = packet.Packet(msg.data)</span><br><span class="line">        eth_pkt = pkt.get_protocol(ethernet.ethernet)</span><br><span class="line">        dst = eth_pkt.dst</span><br><span class="line">        src = eth_pkt.src</span><br><span class="line"></span><br><span class="line">        <span class="comment"># get the received port number from packet_in message.</span></span><br><span class="line">        in_port = msg.match[<span class="string">'in_port'</span>]</span><br><span class="line"></span><br><span class="line">        self.logger.info(<span class="string">"packet in %s %s %s %s"</span>, dpid, src, dst, in_port)</span><br><span class="line"></span><br><span class="line">        <span class="comment"># learn a mac address to avoid FLOOD next time.</span></span><br><span class="line">        self.mac_to_port[dpid][src] = in_port</span><br><span class="line"></span><br><span class="line">        <span class="comment"># if the destination mac address is already learned,</span></span><br><span class="line">        <span class="comment"># decide which port to output the packet, otherwise FLOOD.</span></span><br><span class="line">        <span class="keyword">if</span> dst <span class="keyword">in</span> self.mac_to_port[dpid]:</span><br><span class="line">            out_port = self.mac_to_port[dpid][dst]</span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            out_port = ofproto.OFPP_FLOOD</span><br><span class="line"></span><br><span class="line">        <span class="comment"># construct action list.</span></span><br><span class="line">        actions = [parser.OFPActionOutput(out_port)]</span><br><span class="line"></span><br><span class="line">        <span class="comment"># install a flow to avoid packet_in next time.</span></span><br><span class="line">        <span class="keyword">if</span> out_port != ofproto.OFPP_FLOOD:</span><br><span class="line">            match = parser.OFPMatch(in_port=in_port, eth_dst=dst)</span><br><span class="line">            self.add_flow(datapath, <span class="number">1</span>, match, actions)</span><br><span class="line"></span><br><span class="line">        <span class="comment"># construct packet_out message and send it.</span></span><br><span class="line">        out = parser.OFPPacketOut(datapath=datapath,</span><br><span class="line">                                  buffer_id=ofproto.OFP_NO_BUFFER,</span><br><span class="line">                                  in_port=in_port, actions=actions,</span><br><span class="line">                                  data=msg.data)</span><br><span class="line">        datapath.send_msg(out)</span><br></pre></td></tr></table></figure>
<p>让我们来看看各自实现的内容。</p>
<h3 id="2-3-1-类定义和初始化"><a href="#2-3-1-类定义和初始化" class="headerlink" title="2.3.1 类定义和初始化"></a>2.3.1 类定义和初始化</h3><p>为了实现一个ryu应用， ryu.base.app_manager.RyuApp被引用，此外，要使用OpenFlow 1.3，OpenFlow 1.3版本是为OFP_VERSIONS指定的。此外，定义了MAC地址表mac_to_port.</p>
<p>在OpenFlow协议中，已经定义了一些过程，例如Open-Flow交换机和控制器之间通信所需的握手。但是，由于Ryu的框架负责处理这些程序，因此在ryu app中不需要了解这些。</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">ExampleSwitch13</span><span class="params">(app_manager.RyuApp)</span>:</span></span><br><span class="line">    OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION]</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self, *args, **kwargs)</span>:</span></span><br><span class="line">        super(ExampleSwitch13, self).__init__(*args, **kwargs)</span><br><span class="line">        <span class="comment"># initialize mac address table.</span></span><br><span class="line">        self.mac_to_port = &#123;&#125;</span><br></pre></td></tr></table></figure>
<h3 id="2-3-2-事件处理函数"><a href="#2-3-2-事件处理函数" class="headerlink" title="2.3.2 事件处理函数"></a>2.3.2 事件处理函数</h3><p>对于Ryu，当接收到OpenFlow消息时，生成对应于该消息的事件。 Ryu应用程序实现了与希望接收的消息相对应的事件处理程序。事件处理程序定义了一个具有参数的事件对象的函数，并使用ryu.controller.handler.set_ev_cls装饰器来装饰。</p>
<p>set_ev_cls指定支持接收消息的事件类以及参数的OpenFlow交换机的状态。事件类名称为ryu.controller.ofp_event.EventOFP + <openflow消息名称>。例如，在Packet-In消息的情况下，它变为EventOFPPacketIn。有关详细信息，请参阅Ryu的标题为API Reference的文档。对于状态，请指定以下之一或列表。</openflow消息名称></p>
<div align="center"><img src="http://ipic-picgo.oss-cn-beijing.aliyuncs.com/2019-05-11-053905.jpg" width="800"></div>

<ol>
<li><p>添加缺失流表项</p>
<p>在与OpenFlow交换机完成握手之后，将缺失流表项添加到交换机流表中以准备接收Packet-In消息。具体地，在接收到交换机特征（特征回复）消息时，添加表缺失流条目。</p>
</li>
</ol>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER)</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">switch_features_handler</span><span class="params">(self, ev)</span>:</span></span><br><span class="line">        datapath = ev.msg.datapath</span><br><span class="line">        ofproto = datapath.ofproto</span><br><span class="line">        parser = datapath.ofproto_parser</span><br></pre></td></tr></table></figure>
<p>在ev.msg中，存储与该事件对应的OpenFlow消息类的实例。在本例中，它是ryu.ofproto.ofproto_v1_3_parser.OFPSwitchFeatures。在msg.datapath中，存储与发出此消息的OpenFlow交换机对应的ryu.controller.controller.Datapath类的实例。Datapath类执行重要的处理，例如与OpenFlow交换机的实际通信以及与接收的消息相对应的事件的发布。<br>Ryu应用程序使用的datapath主要属性如下：</p>
<div align="center"><img src="http://ipic-picgo.oss-cn-beijing.aliyuncs.com/2019-05-11-054538.jpg" width="800"></div>

<p>Ryu应用程序中使用的Datapath类的主要方法如下：</p>
<p><code>send_msg（msg）</code></p>
<p>发送OpenFlow消息。 msg是与发送OpenFlow消息对应的ryu.ofproto.ofproto_parser.MsgBase的子类。<br>交换集线器并不特别使用收到的交换机功能消息本身。它被作为事件处理以获得添加表缺失流条目的定时。</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">switch_features_handler</span><span class="params">(self, ev)</span>:</span></span><br><span class="line">        <span class="comment"># install the table-miss flow entry.</span></span><br><span class="line">        match = parser.OFPMatch()</span><br><span class="line">        actions = [parser.OFPActionOutput(ofproto.OFPP_CONTROLLER,</span><br><span class="line">                                          ofproto.OFPCML_NO_BUFFER)]</span><br><span class="line">        self.add_flow(datapath, <span class="number">0</span>, match, actions)</span><br></pre></td></tr></table></figure>
<p>Table-miss流条目具有最低（0）优先级，并且该条目匹配所有分组。在该条目的指令中，通过指定输出到控制器端口的输出动作，如果接收的数据包与任何正常流条目都不匹配，则发出Packet-In。生成空匹配以匹配所有数据包。匹配在OFPMatch类中表示。<br>接下来，生成OUTPUT操作类（OFPActionOutput）的实例以传输到控制器端口。控制器被指定为输出目的地，OFPCML_NO_BUFFER被指定为max_len，以便将所有数据包发送到控制器。<br>最后，为优先级指定0（最低），并执行add_flow（）方法以发送Flow Mod消息。 add_flow（）方法的内容将在后面的部分中介绍。</p>
<ol>
<li><p>Packet-In 消息</p>
<p>创建Packet-In事件处理程序的处理程序，以接受具有未知目标的已接收数据包</p>
</li>
</ol>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">_packet_in_handler</span><span class="params">(self, ev)</span>:</span></span><br><span class="line">        msg = ev.msg</span><br><span class="line">        datapath = msg.datapath</span><br><span class="line">        ofproto = datapath.ofproto</span><br><span class="line">        parser = datapath.ofproto_parser</span><br></pre></td></tr></table></figure>
<p>常用的OFPPacketIn类属性如下所示：</p>
<div align="center"><img src="http://ipic-picgo.oss-cn-beijing.aliyuncs.com/2019-05-11-061623.jpg" width="800"></div>

<ol>
<li>更新MAC地址表</li>
</ol>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">_packet_in_handler</span><span class="params">(self, ev)</span>:</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">        <span class="comment"># get the received port number from packet_in message.</span></span><br><span class="line">        in_port = msg.match[<span class="string">'in_port'</span>]</span><br><span class="line"></span><br><span class="line">        self.logger.info(<span class="string">"packet in %s %s %s %s"</span>, dpid, src, dst, in_port)</span><br><span class="line"></span><br><span class="line">        <span class="comment"># learn a mac address to avoid FLOOD next time.</span></span><br><span class="line">        self.mac_to_port[dpid][src] = in_port</span><br></pre></td></tr></table></figure>
<p>$\qquad$从OFPPacketIn匹配中获取接收端口（in_port）。目标MAC地址和发送方MAC地址使用Ryu的数据包库从接收到的数据包的以太网报头中获取。基于获取的发送方MAC地址和接收的端口号，更新MAC地址表。<br>$\qquad$为了支持与多个OpenFlow交换机的连接，MAC地址表被设计为针对每个OpenFlow交换机进行管理。datapath ID用于标识OpenFlow交换机。</p>
<ol>
<li><p>判断转发目的端口</p>
<p>当MAC地址表中存在目的MAC地址时，使用相应的端口号。如果未找到，则生成OUTPUT操作类的实例，该实例指定输出端口的泛洪（OFPP_FLOOD）</p>
</li>
</ol>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">_packet_in_handler</span><span class="params">(self, ev)</span>:</span></span><br><span class="line"></span><br><span class="line">        <span class="comment"># if the destination mac address is already learned,</span></span><br><span class="line">        <span class="comment"># decide which port to output the packet, otherwise FLOOD.</span></span><br><span class="line">        <span class="keyword">if</span> dst <span class="keyword">in</span> self.mac_to_port[dpid]:</span><br><span class="line">            out_port = self.mac_to_port[dpid][dst]</span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            out_port = ofproto.OFPP_FLOOD</span><br><span class="line"></span><br><span class="line">        <span class="comment"># construct action list.</span></span><br><span class="line">        actions = [parser.OFPActionOutput(out_port)]</span><br><span class="line">        <span class="comment"># install a flow to avoid packet_in next time.</span></span><br><span class="line">        <span class="keyword">if</span> out_port != ofproto.OFPP_FLOOD:</span><br><span class="line">            match = parser.OFPMatch(in_port=in_port, eth_dst=dst)</span><br><span class="line">            self.add_flow(datapath, <span class="number">1</span>, match, actions)</span><br></pre></td></tr></table></figure>
<p>$\qquad$如果找到目标MAC地址，则会在OpenFlow交换机的流表中添加一个条目。与添加Table-miss流条目一样，指定匹配和操作，并执行add_flow（）以添加流条目。</p>
<p>$\qquad$与Table-miss流条目不同，此次设置匹配条件。这次实现了交换集线器，指定了接收端口（in_port）和目标MAC地址（eth_dst）。例如，由端口1接收的寻址到主机B的分组是目标。<br>$\qquad$对于此次的流条目，优先级指定为1,值越大，优先级越高，因此，此处添加的流条目将在Table-miss流条目之前进行评估。<br>$\qquad$根据包含上述操作的摘要，将以下条目添加到流表中。将端口1接收到的主机B（目标MAC地址为B）的数据包传输到端口4。</p>
<blockquote>
<p>对于OpenFlow，在选项中规定了一个名为NORMAL的逻辑输出端口，当为输出端口指定NORMAL时，交换机的L2 / L3功能用于处理数据包。这意味着，通过指示将所有数据包输出到NORMAL端口，可以使交换机作为交换集线器运行。但是，我们使用OpenFlow实现每个处理</p>
</blockquote>
<ol>
<li>添加流表项</li>
</ol>
<p>Packet-In处理程序的处理尚未完成，但这里将介绍添加流表项的方法。</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">add_flow</span><span class="params">(self, datapath, priority, match, actions)</span>:</span></span><br><span class="line">        ofproto = datapath.ofproto</span><br><span class="line">        parser = datapath.ofproto_parser</span><br><span class="line"></span><br><span class="line">        <span class="comment"># construct flow_mod message and send it.</span></span><br><span class="line">        inst = [parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS,</span><br><span class="line">                                             actions)]</span><br></pre></td></tr></table></figure>
<p>对于流表项，设置指示目标数据包条件的匹配，以及指示对数据包的操作，条目优先级和有效时间的指令。在交换集线器实现中，Apply Actions用于设置指令，以便立即使用指定的操作。<br>最后，通过发出Flow Mod消息向流表添加条目</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">add_flow</span><span class="params">(self, datapath, priority, match, actions)</span>:</span></span><br><span class="line">        mod = parser.OFPFlowMod(datapath=datapath, priority=priority,</span><br><span class="line">                                match=match, instructions=inst)</span><br><span class="line">        datapath.send_msg(mod)</span><br></pre></td></tr></table></figure>
<p>与Flow Mod消息对应的类是OFPFlowMod类。生成OFPFlowMod类的实例，并使用Datapath.send_msg（）方法将消息发送到OpenFlow交换机。OFPFlowMod类的构造函数有很多参数。其中许多通常可以是默认值。括号内是默认值。</p>
<ul>
<li><p>datapath</p>
<p>这是支持流表操作的OpenFlow交换机的Datapath类实例。通常，指定从传递给处理程序的事件中获取的那个，例如Packet-In消息。</p>
</li>
<li><p>cookie(0)</p>
<p>控制器指定的可选值，可在更新或删除条目时用作过滤条件。这不用于数据包处理。</p>
</li>
<li><p>cookie_mask(0)</p>
<p>更新或删除条目时，如果指定了0以外的值，则使用条目的cookie值将其用作操作目标条目的过滤器</p>
</li>
<li><p>table_id</p>
<p>指定操作目标流表的表ID</p>
</li>
<li><p>command (ofproto_v1_3.OFPFC_ADD)、</p>
<p>指定要执行的操作。</p>
<div align="center"><img src="http://ipic-picgo.oss-cn-beijing.aliyuncs.com/2019-05-11-064100.jpg" width="600"></div>
</li>
<li><p>idle_timeout(0)</p>
<p>指定此条目的有效期，以秒为单位。如果未引用该条目并且idle_timeout指定的时间过去，则删除该条目。引用该条目时，将重置已用时间。<br>删除条目后，会向控制器发送Flow Removed消息。</p>
</li>
<li><p>hard_timeout (0)</p>
<p>指定此条目的有效期，以秒为单位。与idle_timeout不同，使用hard_timeout，即使引用了条目，也不会重置已用时间。也就是说，无论条目的引用如何，都在指定的时间过去时删除该条目。<br>与idle_timeout一样，当删除条目时，将发送Flow Removed消息。</p>
</li>
<li><p>priority(0)</p>
<p>指定此条目的优先级顺序。值越大，优先级越高。</p>
</li>
<li><p>buffer_id (ofproto_v1_3.OFP_NO_BUFFER)</p>
<p>指定OpenFlow交换机上缓冲的数据包的缓冲区ID。在分组输入消息中通知缓冲区ID，并且当指定的处理与发送两个消息时相同，即，为输出端口和流模式消息指定了OFPP_TABLE的分组输出消息。当命令为OFPFC_DELETE或OFPFC_DELETE_STRICT时，将忽略此项。<br>如果未指定缓冲区ID，请设置OFP_NO_BUFFER</p>
</li>
<li><p>out_port</p>
<p>如果命令为OFPFC_DELETE或OFPFC_DELETE_STRICT，则输出端口将过滤目标条目。如果命令为OFPFC_ADD，OFPFC_MODIFY或OFPFC_MODIFY_STRICT，则忽略该命令。<br>要禁用输出端口的过滤，请指定OFPP_ANY。</p>
</li>
<li><p>out_group(0)</p>
<p>与out_port一样，按输出组过滤。要禁用，请指定OFPG_ANY。</p>
</li>
<li><p>flag(0)</p>
<p>您可以指定以下标志组合</p>
</li>
</ul>
<div align="center"><img src="http://ipic-picgo.oss-cn-beijing.aliyuncs.com/2019-05-11-064628.jpg" width="800"></div>

<ul>
<li><p>match(None)</p>
<p>具体的match</p>
</li>
<li><p>instructions ([])</p>
<p>指定指令列表</p>
</li>
</ul>
<ol>
<li><p>数据包转移</p>
<p>现在我们返回Packet-In处理程序并解释最终处理。无论是否从MAC地址表中找到目的地MAC地址，最后都发出分组输出消息并传送接收的分组。</p>
</li>
</ol>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">_packet_in_handler</span><span class="params">(self, ev)</span>:</span></span><br><span class="line">        out = parser.OFPPacketOut(datapath=datapath,</span><br><span class="line">                                  buffer_id=ofproto.OFP_NO_BUFFER,</span><br><span class="line">                                  in_port=in_port, actions=actions,</span><br><span class="line">                                  data=msg.data)</span><br><span class="line">        datapath.send_msg(out)</span><br></pre></td></tr></table></figure>
<p>与Packet-Out消息对应的类是OFPPacketOut类。 OFPPacketOut的构造函数的参数如下：</p>
<ul>
<li><p>datapath</p>
<p>指定OpenFlow交换机对应的Datapath类的实例</p>
</li>
<li><p>buffer_id</p>
<p>指定OpenFlow上缓冲的数据包的缓冲区ID。如果未缓冲，则指定OFP_NO_BUFFER。</p>
</li>
<li><p>in_port</p>
<p>指定接收数据包的端口。如果不是收到的数据包，则指定OFPP_CONTROLLER</p>
</li>
<li><p>actions</p>
<p>指定操作列表。</p>
</li>
<li><p>data</p>
<p>指定数据包的二进制数据。当为buffer_id指定OFP_NO_BUFFER时使用此方法。使用OpenFlow交换机的缓冲区时，省略</p>
</li>
</ul>
<p>$\qquad$在交换集线器实现中，已经为buffer_id指定了Packet-In消息的buffer_id。如果已禁用Packet-In消息的buffer-id，则为发送数据包的数据指定收到的Packet-In数据包。</p>
<h2 id="2-4-ryu应用执行"><a href="#2-4-ryu应用执行" class="headerlink" title="2.4 ryu应用执行"></a>2.4 ryu应用执行</h2><p>因为xterm是从Mininet启动的，所以使用mn命令启动Mininet环境。要构建的环境具有简单的结构，具有三个主机和一个交换机。<br>mn命令参数如下：</p>
<div align="center"><img src="http://ipic-picgo.oss-cn-beijing.aliyuncs.com/2019-05-11-070404.jpg" width="600"></div>


    </div>

    
    
    
        
      
        <div id="reward-container">
  <div></div>
  <button id="reward-button" disable="enable" onclick="var qr = document.getElementById(&quot;qr&quot;); qr.style.display = (qr.style.display === 'none') ? 'block' : 'none';">
    打赏
  </button>
  <div id="qr" style="display: none;">
        
      
      <div style="display: inline-block">
        <img src="https://ipic-picgo.oss-cn-beijing.aliyuncs.com/20200705000845.png" alt="sunhanwu 支付宝">
        <p>支付宝</p>
      </div>

  </div>
</div>

      

      <footer class="post-footer">
          
            
          
          <div class="post-tags">
            
              <a href="/sunpages/tags/SDN/" rel="tag"># SDN</a>
            
          </div>
        

        

          <div class="post-nav">
            <div class="post-nav-next post-nav-item">
              
                <a href="/sunpages/2019/04/05/lab4/" rel="next" title="页面置换算法实验">
                  <i class="fa fa-chevron-left"></i> 页面置换算法实验
                </a>
              
            </div>

            <span class="post-nav-divider"></span>

            <div class="post-nav-prev post-nav-item">
              
                <a href="/sunpages/2019/04/11/CLI_ss/" rel="prev" title="SSR命令行版本配置">
                  SSR命令行版本配置 <i class="fa fa-chevron-right"></i>
                </a>
              
            </div>
          </div>
        
      </footer>
    
  </div>
  
  
  
  </article>

  </div>


          </div>
          
    
    <div class="comments" id="comments"></div>
  

        </div>
          
  
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside class="sidebar">
    <div class="sidebar-inner">
        
        
        
        
      

      <ul class="sidebar-nav motion-element">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <!--noindex-->
      <div class="post-toc-wrap sidebar-panel">
          <div class="post-toc motion-element"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#2-Switching-Hub"><span class="nav-number">1.</span> <span class="nav-text">2 Switching Hub</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#2-1-Switching-Hub"><span class="nav-number">1.1.</span> <span class="nav-text">2.1 Switching Hub</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#2-2-openflow交换集线器"><span class="nav-number">1.2.</span> <span class="nav-text">2.2 openflow交换集线器</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#2-3-使用Ryu实现交换集线器"><span class="nav-number">1.3.</span> <span class="nav-text">2.3 使用Ryu实现交换集线器</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#2-3-1-类定义和初始化"><span class="nav-number">1.3.1.</span> <span class="nav-text">2.3.1 类定义和初始化</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2-3-2-事件处理函数"><span class="nav-number">1.3.2.</span> <span class="nav-text">2.3.2 事件处理函数</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#2-4-ryu应用执行"><span class="nav-number">1.4.</span> <span class="nav-text">2.4 ryu应用执行</span></a></li></ol></li></ol></div>
        
      </div>
      <!--/noindex-->

      <div class="site-overview-wrap sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
    <img class="site-author-image" itemprop="image"
      src="http://ipic-picgo.oss-cn-beijing.aliyuncs.com/2019-09-12-logo.jpg"
      alt="sunhanwu">
  <p class="site-author-name" itemprop="name">sunhanwu</p>
  <div class="site-description" itemprop="description">Talk is cheap, show me the code!</div>
</div>
  <nav class="site-state motion-element">
      <div class="site-state-item site-state-posts">
        
          <a href="/sunpages/archives/%20%7C%7C%20archive">
        
          <span class="site-state-item-count">29</span>
          <span class="site-state-item-name">博客</span>
        </a>
      </div>
    
      
      
      <div class="site-state-item site-state-categories">
        
          
            <a href="/sunpages/categories/%20%7C%7C%20th">
          
        
        <span class="site-state-item-count">7</span>
        <span class="site-state-item-name">分类</span>
        </a>
      </div>
    
      
      
      <div class="site-state-item site-state-tags">
        
          
            <a href="/sunpages/tags/%20%7C%7C%20tags">
          
        
        <span class="site-state-item-count">18</span>
        <span class="site-state-item-name">标签</span>
        </a>
      </div>
    
  </nav>
  <div class="links-of-author motion-element">
      <span class="links-of-author-item">
      
      
        
      
      
        
      
        <a href="https://github.com/sunhanwu" title="GitHub &rarr; https://github.com/sunhanwu" rel="noopener" target="_blank"><i class="fa fa-fw fa-github"></i>GitHub</a>
      </span>
    
      <span class="links-of-author-item">
      
      
        
      
      
        
      
        <a href="mailto:1965190613@qq.com" title="E-Mail &rarr; mailto:1965190613@qq.com" rel="noopener" target="_blank"><i class="fa fa-fw fa-envelope"></i>E-Mail</a>
      </span>
    
  </div>


  <div class="links-of-blogroll motion-element">
    <div class="links-of-blogroll-title">
      <i class="fa fa-fw fa-link"></i>
      Links
    </div>
    <ul class="links-of-blogroll-list">
        <li class="links-of-blogroll-item">
          <a href="https://jackyanghc.github.io/" title="https://jackyanghc.github.io/" rel="noopener" target="_blank">Jackyanghc</a>
        </li>
      
        <li class="links-of-blogroll-item">
          <a href="https://michel-liu.github.io/" title="https://michel-liu.github.io/" rel="noopener" target="_blank">Michel</a>
        </li>
      
        <li class="links-of-blogroll-item">
          <a href="https://www.cnblogs.com/morwing/" title="https://www.cnblogs.com/morwing/" rel="noopener" target="_blank">morwing</a>
        </li>
      
    </ul>
  </div>

      </div>

    </div>
  </aside>
  <div id="sidebar-dimmer"></div>


      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="footer-inner">
        <div class="copyright">&copy; <span itemprop="copyrightYear">2020</span>
  <span class="with-love" id="animate">
    <i class="fa fa-user"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">sunhanwu</span>
    <span class="post-meta-divider">|</span>
    <span class="post-meta-item-icon">
      <i class="fa fa-area-chart"></i>
    </span>
      <span class="post-meta-item-text">站点总字数：</span>
    
    <span title="站点总字数">161k</span>
    <span class="post-meta-divider">|</span>
    <span class="post-meta-item-icon">
      <i class="fa fa-coffee"></i>
    </span>
      <span class="post-meta-item-text">站点阅读时长 &asymp;</span>
    
    <span title="站点阅读时长">2:26</span>
</div>
  <div class="theme-info">主题 – <a href="https://theme-next.org" class="theme-link" rel="noopener" target="_blank">NexT.Pisces</a> v7.4.0</div>

        












        
      </div>
    </footer>
  </div>

  


  <script src="/sunpages/lib/anime.min.js?v=3.1.0"></script>
  <script src="/sunpages/lib/velocity/velocity.min.js?v=1.2.1"></script>
  <script src="/sunpages/lib/velocity/velocity.ui.min.js?v=1.2.1"></script>

<script src="/sunpages/js/utils.js?v=7.4.0.js"></script>

<script src="/sunpages/js/motion.js?v=7.4.0.js"></script>


<script src="/sunpages/js/schemes/pisces.js?v=7.4.0.js"></script>


<script src="/sunpages/js/next-boot.js?v=7.4.0.js"></script>




  
  <script>
    (function(){
      var bp = document.createElement('script');
      var curProtocol = window.location.protocol.split(':')[0];
      bp.src = (curProtocol === 'https') ? 'https://zz.bdstatic.com/linksubmit/push.js' : 'http://push.zhanzhang.baidu.com/push.js';
      var s = document.getElementsByTagName("script")[0];
      s.parentNode.insertBefore(bp, s);
    })();
  </script>








  
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/instantsearch.js@2/dist/instantsearch.min.css">
<script src="//cdn.jsdelivr.net/npm/instantsearch.js@2/dist/instantsearch.min.js"></script>
<script src="/sunpages/js/algolia-search.js?v=7.4.0.js"></script>
















  

  

  

  


<script>
NexT.utils.getScript('//unpkg.com/valine/dist/Valine.min.js', () => {
  var GUEST = ['nick', 'mail', 'link'];
  var guest = 'nick,mail,link';
  guest = guest.split(',').filter(item => {
    return GUEST.includes(item);
  });
  new Valine({
    el: '#comments',
    verify: false,
    notify: false,
    appId: 'ToSqcWxrMe4Fx1bTFKjHnFQn-gzGzoHsz',
    appKey: 'WIlMiWIudPsl2Q2PsMVfiUUH',
    placeholder: 'Just go go',
    avatar: 'mm',
    meta: guest,
    pageSize: '10' || 10,
    visitor: false,
    lang: '' || 'zh-cn',
    path: location.pathname
  });
}, window.Valine);
</script><!-- hexo-inject:begin --><!-- Begin: Injected MathJax -->
<script type="text/x-mathjax-config">
  MathJax.Hub.Config("");
</script>

<script type="text/x-mathjax-config">
  MathJax.Hub.Queue(function() {
    var all = MathJax.Hub.getAllJax(), i;
    for(i=0; i < all.length; i += 1) {
      all[i].SourceElement().parentNode.className += ' has-jax';
    }
  });
</script>

<script type="text/javascript" src="">
</script>
<!-- End: Injected MathJax -->
<!-- hexo-inject:end -->

</body>
</html>
